import { REQUEST_CONFIG } from "@/config";

/**
 * 请求ui配置
 */
export interface RequestUiConfig {
  /**
   * 错误提示
   */
  errorToast: boolean;
}

/**
 * 请求配置
 */
export type RequestConfig = Omit<
  UniNamespace.RequestOptions,
  "success" | "fail" | "complete" | "method"
> & {
  /**
   * ui配置
   */
  uiConfig?: RequestUiConfig;
  /**
   * 请求方法
   */
  method: "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD";
};

/**
 * 请求结果
 */
export interface RequestResult<D> {
  code: number;
  data: D;
  message: string;
}

/**
 * 请求失败结果
 */
export interface RequestFailResult {
  code: number;
  message: string;
  /** 是否业务出错  */
  isBusinessError: boolean;
}

export const request = <D>(configInit: RequestConfig) => {
  return new Promise<RequestResult<D>>((resolve, reject) => {
    const { uiConfig, url, header = {}, ...config } = configInit;

    const { errorToast = true } = uiConfig || {};

    uni.request({
      timeout: REQUEST_CONFIG.timeout,
      ...config,
      header: {
        ...REQUEST_CONFIG.getHeader(),
        ...(header || {}),
      },
      url: `${REQUEST_CONFIG.basePath}${url}`,
      success: async (res) => {
        const { data: dataInit, statusCode, errMsg } = res;

        const data: RequestResult<D> = dataInit as RequestResult<D>;

        // 判断网关是否成功 默认2xx 都会认为成功 此处可以根据项目自行判断
        if (REQUEST_CONFIG.gatewaySuccessCodeList.includes(statusCode)) {
          // 判断业务是否成功
          if (REQUEST_CONFIG.businessSuccessCodeList.includes(data.code)) {
            resolve(data);
          } else {
            // 业务失败

            const {
              canShowErrorToast,
              reload,
              newError = data,
            } = await REQUEST_CONFIG.dealBusinessError({
              ...data,
              isBusinessError: true,
            } satisfies RequestFailResult);

            if (reload) {
              resolve(request(configInit));
            } else {
              REQUEST_CONFIG.showToast(
                newError.message,
                canShowErrorToast && errorToast,
              );

              reject(newError);
            }
          }
        } else {
          // 网关转失败
          const message =
            errMsg || (statusCode && `${statusCode}`) || "响应出错";

          REQUEST_CONFIG.showToast(message, errorToast);

          // eslint-disable-next-line prefer-promise-reject-errors
          reject({
            code: statusCode,
            message,
            isBusinessError: false,
          } satisfies RequestFailResult);
        }
      },
      fail: (err) => {
        // 网络请求失败
        const { errno, errNo, errMsg } = err as any;

        const message = errMsg || errNo || errno || "请求失败";

        REQUEST_CONFIG.showToast(message, errorToast);

        // eslint-disable-next-line prefer-promise-reject-errors
        reject({
          code: errno || errNo || -1,
          message,
          isBusinessError: false,
        } satisfies RequestFailResult);
      },
      complete: () => {},
    });
  });
};
